/*
 * TMap Designer - A Thematic Map design software
 * Copyright (C) 2006 World Health Organization
 * http://www.who.int
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package who.tmap.toolkit.cdr.impl;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.TexturePaint;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.util.Iterator;
import java.util.Map;

import org.apache.log4j.Logger;

import who.tmap.bo.cd.CartographicDisplay;
import who.tmap.common.TMapException;
import who.tmap.services.TextureService;
import who.tmap.toolkit.MappingToolKit;
import who.tmap.toolkit.cdr.CDRepresentation;
import who.tmap.toolkit.shape.MapShape;

public abstract class BaseCDRImpl implements CDRepresentation {

    private static Logger logger = Logger.getLogger(BaseCDRImpl.class); 
    private static final TextureService textureHelper =TextureService.getInstance();
	
	protected MappingToolKit mtk =null;
	protected CartographicDisplay cd =null;
	protected double minVal, maxVal, diffVal;
	protected double mapFactor =1.d;
	
	public void init( MappingToolKit mtk, CartographicDisplay cd, double mapFactor ) throws TMapException {
		this.mtk =mtk;
		this.cd =cd;
		this.mapFactor =mapFactor;
	}
	
	protected void drawShape( Graphics2D g, Shape shape, Color color, int fillPattern ) {
		Area area =new Area( shape );
		AffineTransform prevTransform =g.getTransform();
		Area newArea = area.createTransformedArea( prevTransform );

		g.setTransform( new AffineTransform() );

		Color prevColor =g.getColor();
		Composite prevComposite =g.getComposite();
		Paint prevPaint =g.getPaint();
		
		g.setColor( color );	
		
		TexturePaint tp =textureHelper.getTexturePaint()[ fillPattern ];
		
		if ( tp != null ) {
			// Color the background first
			if ( color != null ) {
				g.fill( newArea );
			}
			
			g.setComposite( AlphaComposite.getInstance( TextureService.CD_ALPHA_RULE, TextureService.CD_ALPHA_COMPOSITE ) );

			g.setPaint( tp );	
		} 
	
		g.draw( newArea );
		if ( color != null ) {
			g.fill( newArea );
		}
		
		g.setTransform( prevTransform );
		g.setPaint( prevPaint );
		g.setComposite( prevComposite );
		g.setColor( prevColor );
	}
		
	protected Object getVal( MapShape shape ) {
		Object val =null;
			
		Map<MapShape,Object> data =cd != null ? cd.getPolygonAssociatedData() : null;
		
		val =data != null ? data.get( shape ) : null;
		
		return val;
	}
	
	protected double getDoubleVal( MapShape shape ) {
		Object val =getVal( shape );
		
		double dbl =Double.MIN_VALUE;
		if ( val != null ) {
			dbl =getDoubleValue( val.toString() );
		}
		
		return dbl;
	}
	
    /**
     * Convert an object (Integer, Float, Double) into a double)
     * @param in the object to convert
     * @return the double value
     */
    protected double getDoubleValue( String val ) {
        double dbl;
        
        // Try with an integer first
        try {
        	dbl =Integer.parseInt( val );
        } catch( Exception e ) {
        	try {
        		// then with a double
        		dbl =Double.parseDouble( val );
        	} catch( Exception e2 ) {
        		// set to 0 otherwise
        		dbl =0;
    			//logger.error( "Invalid value=[" + val + "]" );        		
        	}
        }
        
        return dbl;
    }	
    
    protected double getDoubleValue( Object val ) {
    	if ( val instanceof String ) {
    		return getDoubleValue( (String)val );
    	} else {
    		return ((Number)val).doubleValue();
    	}
    }
    
	/**
	 * Process the min, max and delta values of the data
	 * @param cd
	 * @return a double array containing the min, max and delta values
	 */
	protected void processRanges( CartographicDisplay cd ) {
		double min =Double.MAX_VALUE, max =Double.MIN_VALUE;
		
		if ( cd != null && cd.getPolygonAssociatedData() != null ) {
			Map<MapShape, Object> data =cd.getPolygonAssociatedData();
			
			Iterator<Object> it =data.values().iterator();
			while( it.hasNext() ) {
				Object obj =it.next();
				if ( obj != null ) {
					String val =obj.toString();
					double dbl =getDoubleValue( val );
									
					if ( min > dbl ) {
						min =dbl;
					}
					
					if ( max < dbl ) {
						max =dbl;
					}
				}
			}
		}
		
		minVal =min != Double.MAX_VALUE ? min : 0;
		maxVal =max != Double.MIN_VALUE ? max : 0;
		diffVal =maxVal - minVal;
	}
	
}
